Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate a reusable Image class from Screen #834

Merged
merged 5 commits into from
Apr 27, 2024
Merged

Separate a reusable Image class from Screen #834

merged 5 commits into from
Apr 27, 2024

Conversation

Epixu
Copy link
Contributor

@Epixu Epixu commented Mar 29, 2024

Context:

I'm making a custom ASCII rasterizer of sorts, and I needed direct control on what's rendered to a Canvas. So I took the liberty to make some changes:

Main changes:

  1. Separated Image from Screen to avoid tinkering with Windows console on construction
  2. Added Canvas::DrawPixel and Canvas::DrawImage

Example use case:

Image backbuffer;
// (...render to backbuffer or load an 'image'...)
auto component = Renderer([&] {
  auto my_image = canvas([&](Canvas& c) {
     c.DrawPointLine(0, 0, c.width(), c.height());
     c.DrawImage(0, 0, backbuffer); // directly draw the pixels of the image
  });
  return my_image | flex;
});

Secondary changes:

a. Added Box::Area method for convenience
b. .gitignored autogenerated directory by MSVC's CMake integration

Considerations:

I did run the tests on windows 10, they sometimes run, sometimes fail at these interrupt tests, not sure if this is normal or not:

TEST(ScreenInteractive, Signal_SIGTERM) {
TestSignal(SIGTERM);
}
TEST(ScreenInteractive, Signal_SIGSEGV) {
TestSignal(SIGSEGV);
}
TEST(ScreenInteractive, Signal_SIGINT) {
TestSignal(SIGINT);
}
TEST(ScreenInteractive, Signal_SIGILL) {
TestSignal(SIGILL);
}
TEST(ScreenInteractive, Signal_SIGABRT) {
TestSignal(SIGABRT);
}
TEST(ScreenInteractive, Signal_SIGFPE) {
TestSignal(SIGFPE);
}

Additional notes:

I might be doing more occasional pull requests in the future, including regarding my issue #778 - I have a couple of optimizations in mind for the near future. If you think these changes are out of the scope of your library and don't need the spam, inform me and I'll stick to a fork!

All the best,
Dimo Markov

…Added Canvas methods for drawing Pixels/Images directly
@ArthurSonzogni
Copy link
Owner

Excellent! I like it!

@Epixu
Copy link
Contributor Author

Epixu commented Mar 30, 2024

Okay, but don't merge it yet, I'll add tests for it, as well as some bug fixes. I'll add a couple of more commits to this one :)

.gitignore Show resolved Hide resolved
@@ -15,6 +15,7 @@ struct Box {
static auto Intersection(Box a, Box b) -> Box;
static auto Union(Box a, Box b) -> Box;
bool Contain(int x, int y) const;
int Area() const noexcept;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FTXUI already ban using C++ exception. I would remove the noexcept here, because it feel superfluous and inconsistent with every other functions.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about adding Width() and Height() instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted about noexcept
I can add Width() and Height() also, but it is often used like if (Width() > 0 and Height() > 0) when checking boxes, so i decided it would be most convenient to check it through the area, with the added benefit of checking for negatives

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about Area::IsEmpty()?

(I pushed a patch for adding it instead)

@@ -0,0 +1,87 @@
// Copyright 2020 Arthur Sonzogni. All rights reserved.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2024

Comment on lines 17 to 52
/// @brief A unicode character and its associated style.
/// @ingroup screen
struct Pixel {
Pixel()
: blink(false),
bold(false),
dim(false),
inverted(false),
underlined(false),
underlined_double(false),
strikethrough(false),
automerge(false) {}

// A bit field representing the style:
bool blink : 1;
bool bold : 1;
bool dim : 1;
bool inverted : 1;
bool underlined : 1;
bool underlined_double : 1;
bool strikethrough : 1;
bool automerge : 1;

// The hyperlink associated with the pixel.
// 0 is the default value, meaning no hyperlink.
// It's an index for accessing Screen meta data
uint8_t hyperlink = 0;

// The graphemes stored into the pixel. To support combining characters,
// like: a?, this can potentially contain multiple codepoints.
std::string character = " ";

// Colors:
Color background_color = Color::Default;
Color foreground_color = Color::Default;
};
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While you are here, this might deserve its own file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(done)

for (int py = y; py < yend; ++py) {
for (int px = x; px < xend; ++px) {
Cell& cell = storage_[XY{px, py}];
cell.type = CellType::kText; // Epixu: should we add kCustom or something?
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kText sounds appropriate to me. We are covering the whole cell.

Copy link
Contributor Author

@Epixu Epixu Apr 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But kText seems a bit weird in that context, probably rename those to:
CellType::BrailleSegment, CellType::BlockSegment, and CellType::Uniform ?
Probably doesn't matter too much, but still?
Because I'm having some ideas about drawing text, but large and segmented, like big ASCII letters. Here's an example:

    _    ____   ____ ___ ___      _         _        _             _     _           
   / \  / ___| / ___|_ _|_ _|    / \   _ __| |_     / \   _ __ ___| |__ (_)_   _____ 
  / _ \ \___ \| |    | | | |    / _ \ | '__| __|   / _ \ | '__/ __| '_ \| \ \ / / _ \
 / ___ \ ___) | |___ | | | |   / ___ \| |  | |_   / ___ \| | | (__| | | | |\ V /  __/
/_/   \_\____/ \____|___|___| /_/   \_\_|   \__| /_/   \_\_|  \___|_| |_|_| \_/ \___|

src/ftxui/screen/image.cpp Show resolved Hide resolved
@Epixu
Copy link
Contributor Author

Epixu commented Apr 12, 2024

Thanks for the support, I'm sorry that I'm a bit slow on this, but I've got a lot of stuff on my backlog

@ArthurSonzogni ArthurSonzogni merged commit 293ff17 into ArthurSonzogni:main Apr 27, 2024
9 checks passed
@ArthurSonzogni
Copy link
Owner

Merged! Thanks for your patience!

@Epixu
Copy link
Contributor Author

Epixu commented May 10, 2024

With these changes, I was able to resterize and display this:
image
Just thought it would be fun to share :)

@ArthurSonzogni
Copy link
Owner

Nice 3D renderer !

ArthurSonzogni added a commit that referenced this pull request Dec 26, 2024
Co-authored-by: ArthurSonzogni <sonzogniarthur@gmail.com>
ArthurSonzogni added a commit that referenced this pull request Dec 26, 2024
Co-authored-by: ArthurSonzogni <sonzogniarthur@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants